iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
Vibe Coding

從 GAS 到 Cloudflare D1:AI Agent 如何打造、接手並重構真實便當系統系列 第 4

Day 4|當 GAS + Sheets 真的開始被使用後,試算表就不再只是試算表

  • 分享至 

  • xImage
  •  

Day 4

Day 3 提到,第一版手機版便當系統之所以選擇 GAS + Google Sheets,不是因為它是什麼完美架構。

而是因為當時我要解決的問題很實際:

  • 手機可以用
  • 開發速度快
  • 資料方便查看
  • 不想一開始就架一套完整 Backend

這個選擇確實有效。

系統很快就從「我腦中的想法」變成:

真的有人每天拿來訂便當的東西。

而問題也正是從這裡開始。

因為當一張 Sheet 裡面的資料,開始代表:

  • 誰今天真的訂了一份餐
  • 1F、9F 各要送幾份
  • 店家今天到底要準備多少便當
  • 某個人現在到底還剩多少錢

它已經不能只被當成一張方便看的試算表,而是開始承擔正式系統才會遇到的責任。


最初我最喜歡的優點,後來反而變成第一個警訊

Google Sheets 最大的優點是什麼?

對我來說一直都很明確:

資料看得到。

打開表格,就可以直接看到使用者、菜單、訂單、金額與管理資料。

不需要另外開 SQL Tool,也不需要一開始就做完整後台。

如果某個同事說:

我的訂單好像怪怪的。

直接查 Sheet 就能開始確認。

第一版剛開始跑的時候,這種透明度非常舒服。

但慢慢地,我開始發現一件事:

資料看得到,不代表資料可以隨便動。

這兩件事,差很多。


一列訂單開始代表真實行動

假設 Sheet 裡現在有這樣一列:

日期:2026/09/18
姓名:小明
餐點:A 餐
樓層:9F
數量:1

如果只從技術角度看,它可能真的只是一筆資料。

但在真實流程裡,它代表的是:

明天真的要多準備一份便當。

如果這一列被誤刪,影響的不只是少一筆測試資料,而是有一個人可能真的沒有便當吃。

這就是第一個明顯的轉折。

當資料開始直接連到真實世界,資料錯誤的成本就不再只是 Debug 一下就好。


統計、樓層,也開始變成營運的一部分

便當系統有一個看起來很普通的功能:

統計今天各種餐點有幾份。

技術上,它很容易讓人聯想到:

COUNT
SUM
GROUP BY

但這個數字的用途,是拿來向店家下單。

如果畫面顯示:

A 餐:10
B 餐:8

實際上卻應該是:

A 餐:11
B 餐:8

那少掉的那個 1,不是報表誤差。

是:

店家真的少做一份。

取餐樓層也一樣。

1F9F 看起來只是欄位值,但最後會直接影響:

使用者訂單
↓
樓層統計
↓
實際分餐

統計不是附加功能,樓層也不是普通欄位。

它們都已經是營運流程的一部分。


金額出現後,事情又再變一次

讓我最明顯感受到系統責任變化的,是餘額。

一開始的想法很直覺。

大家先儲值,訂便當時扣錢,取消時再加回去。

看起來只是:

餘額 = 原餘額 - 餐費

或者:

餘額 = 原餘額 + 退款

但一旦真的開始使用,問題就會變成:

  • 為什麼現在是 700 元?
  • 哪一天儲值的?
  • 剛剛那筆訂單有沒有扣成功?
  • 如果重複送出會不會扣兩次?
  • 取消之後有沒有真的加回來?
  • 如果人工修改過資料,要怎麼知道?
  • 畫面上的餘額跟歷史計算不一樣時,要相信哪一個?

這些問題已經完全超過:

Sheet 裡有一個 balance 欄位。

因為當數字開始代表錢,使用者在意的不是:

資料有沒有存進去。

而是:

這個數字可不可信。


我後來開始把資料分成三種

這個階段,我慢慢形成一個很實用的觀念:

不是所有資料,都應該被當成同一種東西。

至少可以先粗略分成三類。

1. Input

使用者或管理者真的輸入的資料。

例如:

  • 訂哪一餐
  • 數量
  • 取餐樓層
  • 備註

這些是事件的輸入。

2. Derived Result

由其他資料計算出來的結果。

例如:

  • 今天 A 餐總共有幾份
  • 1F 有幾份
  • 9F 有幾份
  • 今日總金額

這些通常不應該靠人手直接改。

它們應該由:

真實訂單重新算出來。

3. Authoritative Record

用來回答:

到底發生了什麼?

的紀錄。

例如:

  • 一筆訂單是否真的成立
  • 是否已取消
  • 某筆儲值是否真的發生
  • 某個調整是不是管理者執行過

這類資料一旦開始牽涉金額與歷史,就不能只是:

現在畫面看起來是對的。

而是要能追得回來。


資料可見性,不等於資料權威

Google Sheets 很容易讓人產生一個錯覺。

因為所有資料都直接攤在眼前,所以會很自然覺得:

我看到的這格,就是答案。

但實際系統通常會慢慢出現很多不同來源:

使用者輸入
↓
訂單
↓
統計結果
↓
餘額
↓
管理員調整

如果沒有先想清楚:

哪一份資料才是 Source of Truth?

久了就會出現很麻煩的狀況。

例如:

訂單顯示:已取消
餘額顯示:還沒加回去
統計顯示:仍然包含這份餐

三個畫面可能 individually 都有自己的邏輯,

但整體已經不一致。

最難 Debug 的,通常就是這種問題。


Validation 也開始變成 Business Rule

早期做表單時,很容易把 Validation 想成:

  • 姓名必填
  • 數量必填
  • 餐點必選

但系統開始真的被使用後,Validation 往往會變成:

  • 這個日期現在還能不能訂?
  • 這個餐點今天還有效嗎?
  • 這個使用者餘額夠不夠?
  • 這筆訂單是不是已經取消?
  • 這個動作會不會被重複執行?

這些都不是:

required=true

可以解決的。

它們是:

系統必須替真實世界守住的規則。


什麼時候 Prototype 已經開始變成 System?

如果現在回頭看,我覺得有幾個很明顯的訊號。

訊號 代表什麼
資料開始影響真實行動 統計錯誤會讓店家做錯數量
出現金額 錯誤開始影響信任
多種角色會操作資料 需要權限與修改邊界
同一資料有多個寫入來源 開始需要明確 Source of Truth
歷史資料不能亂改 開始需要追溯性
一次錯誤會影響後續流程 Validation 與一致性變重要
使用者真的依賴它 「偶爾壞掉」開始有成本

當這些東西開始出現時,系統其實已經跨過某一條線。

它不再只是:

做出來看看。

而是:

真的有人把流程交給它了。


這不是 GAS + Sheets 的問題

如果只看到後面的架構演進,很容易得出一個很簡單的結論:

所以 Google Sheets 不適合做正式系統。

但我並不這樣看。

對第一版來說,GAS + Sheets 非常成功。

如果當時一開始就要求:

  • 完整 Backend
  • 正式 Database
  • 完整身份系統
  • 權限模型
  • 歷史版本
  • Deployment Pipeline

很可能第一版根本不會那麼快被使用。

而如果沒有人真的使用,很多後面的問題也根本不會被看見。

這段演進不是:

原本選錯工具。

而是:

原本合理的工具,成功把系統送進下一個階段。

然後下一個階段,有了新的責任。


開始改變的是責任

Day 3 的時候,我用 GAS + Google Sheets 換到了一個非常重要的東西:

快速進入真實使用。

而 Day 4 這個階段開始出現的是另一件事:

真實使用開始反過來要求系統負責。

訂單開始連到實際備餐,樓層會影響分餐,統計會影響店家下單,餘額則直接關係到信任。

它們都開始連到真實的人與真實流程。

這也是我後來一路從:

能不能做出來?

慢慢走向:

做出來之後,能不能相信它?

的起點。


本系列實作專案

這不是純概念示範,而是一套持續開發中的便當訂購系統。文章著重「為什麼」,GitHub 保留實際程式碼、文件與演進紀錄。

GitHub:https://github.com/henryfir456/bento-order-app


下一篇

當時系統還有另一個變化正在發生。

一開始很多東西之所以看起來很簡單,只是因為環境幫我偷偷回答了很多問題。

例如:

店家是哪一家?

菜單是哪一份?

價格是多少?

幾點截止?

當系統只有固定店家時,這些東西甚至不需要被特別設計。

但當第二家、第三家店開始出現,原本藏在環境裡的「固定值」,

就會一個一個變成:

系統必須正式管理的資料。


上一篇
Day 3|為什麼第一版手機版便當系統,我選了 GAS + Google Sheets?
下一篇
Day 5|一家店變成多家店後,原本固定的東西全變成資料
系列文
從 GAS 到 Cloudflare D1:AI Agent 如何打造、接手並重構真實便當系統9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言